home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / glass / glass.lha / GLASS / widgets / Toggle.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-01  |  16.2 KB  |  590 lines

  1. #ifndef lint
  2. static char Xrcsid[] = "$XConsortium: Toggle.c,v 1.15 89/12/11 15:22:59 kit Exp $";
  3. #endif /* lint */
  4.  
  5. /*
  6.  * Copyright 1989 Massachusetts Institute of Technology
  7.  *
  8.  * Permission to use, copy, modify, distribute, and sell this software and its
  9.  * documentation for any purpose is hereby granted without fee, provided that
  10.  * the above copyright notice appear in all copies and that both that
  11.  * copyright notice and this permission notice appear in supporting
  12.  * documentation, and that the name of M.I.T. not be used in advertising or
  13.  * publicity pertaining to distribution of the software without specific,
  14.  * written prior permission.  M.I.T. makes no representations about the
  15.  * suitability of this software for any purpose.  It is provided "as is"
  16.  * without express or implied warranty.
  17.  *
  18.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  19.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  20.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  21.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  22.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
  23.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  24.  *
  25.  */
  26.  
  27. /*
  28.  * Toggle.c - Toggle button widget
  29.  *
  30.  * Author: Chris D. Peterson
  31.  *         MIT X Consortium 
  32.  *         kit@expo.lcs.mit.edu
  33.  *  
  34.  * Date:   January 12, 1989
  35.  *
  36.  */
  37.  
  38. #include <stdio.h>
  39. #include <X11/IntrinsicP.h>
  40. #include <X11/StringDefs.h>
  41. #include <X11/Xaw/XawInit.h>
  42. #include <X11/Xmu/Misc.h>
  43. #include "ToggleP.h"
  44.  
  45. /****************************************************************
  46.  *
  47.  * Full class record constant
  48.  *
  49.  ****************************************************************/
  50.  
  51. /* Private Data */
  52.  
  53. /* This is a hack, see the comments in ClassInit(). */
  54.  
  55. extern XtActionList xaw_command_actions_list;
  56.  
  57. /* 
  58.  * The order of toggle and notify are important, as the state has
  59.  * to be set when we call the notify proc.
  60.  */
  61.  
  62. static char defaultTranslations[] =
  63.     "<EnterWindow>:        highlight(Always)    \n\
  64.      <LeaveWindow>:        unhighlight()    \n\
  65.      <Btn1Down>,<Btn1Up>:   toggle() notify()";
  66.  
  67. #define offset(field) XtOffset(ToggleWidget, field)
  68.  
  69. static XtResource resources[] = { 
  70.    {XtNstate, XtCState, XtRBoolean, sizeof(Boolean), 
  71.       offset(command.set), XtRString, "off"},
  72.    {XtNradioGroup, XtCWidget, XtRWidget, sizeof(Widget), 
  73.       offset(toggle.widget), XtRWidget, (caddr_t) NULL },
  74.    {XtNradioData, XtCRadioData, XtRPointer, sizeof(caddr_t), 
  75.       offset(toggle.radio_data), XtRPointer, (caddr_t) NULL },
  76. };
  77.  
  78. #undef offset
  79.  
  80. /* Action proceedures retrieved from the command widget */
  81.  
  82. static void Toggle(), Initialize(), Notify(), ToggleSet();
  83. static void ToggleDestroy(), ClassInit();
  84. static Boolean SetValues();
  85.  
  86. /* Functions for handling the Radio Group. */
  87.  
  88. static RadioGroup * GetRadioGroup();
  89. static void CreateRadioGroup(), AddToRadioGroup(), TurnOffRadioSiblings();
  90. static void RemoveFromRadioGroup();
  91.  
  92. static XtActionsRec actionsList[] =
  93. {
  94.   {"toggle",            Toggle},
  95.   {"notify",            Notify},
  96.   {"set",            ToggleSet},
  97. };
  98.  
  99. #define SuperClass ((CommandWidgetClass)&commandClassRec)
  100.  
  101. ToggleClassRec toggleClassRec = {
  102.   {
  103.     (WidgetClass) SuperClass,        /* superclass          */    
  104.     "Toggle",                /* class_name          */
  105.     sizeof(ToggleRec),            /* size              */
  106.     ClassInit,                /* class_initialize      */
  107.     NULL,                /* class_part_initialize  */
  108.     FALSE,                /* class_inited          */
  109.     Initialize,                /* initialize          */
  110.     NULL,                /* initialize_hook      */
  111.     XtInheritRealize,            /* realize          */
  112.     actionsList,            /* actions          */
  113.     XtNumber(actionsList),        /* num_actions          */
  114.     resources,                /* resources          */
  115.     XtNumber(resources),        /* resource_count      */
  116.     NULLQUARK,                /* xrm_class          */
  117.     FALSE,                /* compress_motion      */
  118.     TRUE,                /* compress_exposure      */
  119.     TRUE,                /* compress_enterleave    */
  120.     FALSE,                /* visible_interest      */
  121.     NULL,                     /* destroy          */
  122.     XtInheritResize,            /* resize          */
  123.     XtInheritExpose,            /* expose          */
  124.     SetValues,                /* set_values          */
  125.     NULL,                /* set_values_hook      */
  126.     XtInheritSetValuesAlmost,        /* set_values_almost      */
  127.     NULL,                /* get_values_hook      */
  128.     NULL,                /* accept_focus          */
  129.     XtVersion,                /* version          */
  130.     NULL,                /* callback_private      */
  131.     defaultTranslations,        /* tm_table          */
  132.     XtInheritQueryGeometry,        /* query_geometry      */
  133.     XtInheritDisplayAccelerator,    /* display_accelerator      */
  134.     NULL                /* extension          */
  135.   },  /* CoreClass fields initialization */
  136.   {
  137.     XtInheritChangeSensitive        /* change_sensitive      */ 
  138.   },  /* SimpleClass fields initialization */
  139.   {
  140.     0                                     /* field not used    */
  141.   },  /* LabelClass fields initialization */
  142.   {
  143.     0                                     /* field not used    */
  144.   },  /* CommmandClass fields initialization */
  145.   {
  146.       NULL,                    /* Set Proceedure. */
  147.       NULL,                    /* Unset Proceedure. */
  148.       NULL                    /* extension. */
  149.   }  /* ToggleClass fields initialization */
  150. };
  151.  
  152.   /* for public consumption */
  153. WidgetClass toggleWidgetClass = (WidgetClass) &toggleClassRec;
  154.  
  155. /****************************************************************
  156.  *
  157.  * Private Procedures
  158.  *
  159.  ****************************************************************/
  160.  
  161. static void
  162. ClassInit()
  163. {
  164.   XtActionList actions;
  165.   Cardinal i;
  166.   ToggleWidgetClass class = (ToggleWidgetClass) toggleWidgetClass;
  167.  
  168.   XawInitializeWidgetSet();
  169.  
  170. /* actions = SuperClass->core_class.actions; */
  171.  
  172. /* The actions table should really be retrieved from the toggle widget's
  173.  * Superclass, but this information is munged by the R3 intrinsics so the
  174.  * I have hacked the Athena command widget to export its action table
  175.  * as a global variable.
  176.  *
  177.  * Chris D. Peterson 12/28/88.
  178.  */
  179.  
  180.    actions = xaw_command_actions_list;
  181.  
  182. /* 
  183.  * Find the set and unset actions in the command widget's action table. 
  184.  */
  185.  
  186.   for (i = 0 ; i < SuperClass->core_class.num_actions ; i++) {
  187.     if (streq(actions[i].string, "set"))
  188.     class->toggle_class.Set = actions[i].proc;
  189.     if (streq(actions[i].string, "unset")) 
  190.     class->toggle_class.Unset = actions[i].proc;
  191.  
  192.     if ( (class->toggle_class.Set != NULL) &&
  193.      (class->toggle_class.Unset != NULL) ) return;
  194.   }  
  195.  
  196. /* We should never get here. */
  197.   if (class->toggle_class.Set == NULL)
  198.     XtWarning(
  199.      "Toggle could not find action Proceedure Set() in the Command Widget.");
  200.   if (class->toggle_class.Unset == NULL)
  201.     XtWarning(
  202.      "Toggle could not find action Proceedure Unset() in the Command Widget.");
  203.   XtError("Aborting, due to errors in Toggle widget.");
  204. }
  205.  
  206. static void Initialize(request, new)
  207.  Widget request, new;
  208. {
  209.     ToggleWidget tw = (ToggleWidget) new;
  210.     ToggleWidget tw_req = (ToggleWidget) request;
  211.  
  212.     tw->toggle.radio_group = NULL;
  213.  
  214.     if (tw->toggle.radio_data == NULL) 
  215.       tw->toggle.radio_data = (caddr_t) new->core.name;
  216.  
  217.     if (tw->toggle.widget != NULL) {
  218.       if ( GetRadioGroup(tw->toggle.widget) == NULL) 
  219.     CreateRadioGroup(new, tw->toggle.widget);
  220.       else
  221.     AddToRadioGroup( GetRadioGroup(tw->toggle.widget), new);
  222.     }      
  223.     XtAddCallback(new, XtNdestroyCallback, ToggleDestroy, NULL);
  224.  
  225. /*
  226.  * Command widget assumes that the widget is unset, so we only 
  227.  * have to handle the case where it needs to be set.
  228.  *
  229.  * If this widget is in a radio group then it may cause another
  230.  * widget to be unset, thus calling the notify proceedure.
  231.  *
  232.  * I want to set the toggle if the user set the state to "On" in 
  233.  * the resource group, reguardless of what my ancestors did.
  234.  */
  235.  
  236.     if (tw_req->command.set)
  237.       ToggleSet(new, NULL, NULL, 0);
  238. }
  239.  
  240. /************************************************************
  241.  *
  242.  *  Action Procedures
  243.  *
  244.  ************************************************************/
  245.  
  246. /* ARGSUSED */
  247. static void 
  248. ToggleSet(w,event,params,num_params)
  249. Widget w;
  250. XEvent *event;
  251. String *params;        /* unused */
  252. Cardinal *num_params;    /* unused */
  253. {
  254.     ToggleWidgetClass class = (ToggleWidgetClass) w->core.widget_class;
  255.  
  256.     TurnOffRadioSiblings(w);
  257.     class->toggle_class.Set(w, event, NULL, 0);
  258. }
  259.  
  260. /* ARGSUSED */
  261. static void 
  262. Toggle(w,event,params,num_params)
  263. Widget w;
  264. XEvent *event;
  265. String *params;        /* unused */
  266. Cardinal *num_params;    /* unused */
  267. {
  268.   ToggleWidget tw = (ToggleWidget)w;
  269.   ToggleWidgetClass class = (ToggleWidgetClass) w->core.widget_class;
  270.  
  271.   if (tw->command.set) 
  272.     class->toggle_class.Unset(w, event, NULL, 0);
  273.   else 
  274.     ToggleSet(w, event, params, num_params);
  275. }
  276.  
  277. /* ARGSUSED */
  278. static void Notify(w,event,params,num_params)
  279. Widget w;
  280. XEvent *event;
  281. String *params;        /* unused */
  282. Cardinal *num_params;    /* unused */
  283. {
  284.   ToggleWidget tw = (ToggleWidget) w;
  285.   XtCallCallbacks(w, XtNcallback, tw->command.set);
  286. }
  287.  
  288. /************************************************************
  289.  *
  290.  * Set specified arguments into widget
  291.  *
  292.  ***********************************************************/
  293.  
  294. /* ARGSUSED */
  295. static Boolean 
  296. SetValues (current, request, new)
  297. Widget current, request, new;
  298. {
  299.     ToggleWidget oldtw = (ToggleWidget) current;
  300.     ToggleWidget tw = (ToggleWidget) new;
  301.  
  302.     if (oldtw->toggle.widget != tw->toggle.widget)
  303.       XawToggleChangeRadioGroup(new, tw->toggle.widget);
  304.  
  305.     if (oldtw->command.set != tw->command.set) {
  306.     tw->command.set = oldtw->command.set;
  307.     Toggle(new, NULL, NULL, 0); /* Does a redisplay. */
  308.     }
  309.     return(FALSE);
  310. }
  311.  
  312. /*    Function Name: ToggleDestroy
  313.  *    Description: Destroy Callback for toggle widget.
  314.  *    Arguments: w - the toggle widget that is being destroyed.
  315.  *                 junk, grabage - not used.
  316.  *    Returns: none.
  317.  */
  318.  
  319. /* ARGSUSED */
  320. static void
  321. ToggleDestroy(w, junk, garbage)
  322. Widget w;
  323. caddr_t junk, garbage;
  324. {
  325.   RemoveFromRadioGroup(w);
  326. }
  327.  
  328. /************************************************************
  329.  *
  330.  * Below are all the private proceedures that handle 
  331.  * radio toggle buttons.
  332.  *
  333.  ************************************************************/
  334.  
  335. /*    Function Name: GetRadioGroup
  336.  *    Description: Gets the radio group associated with a give toggle
  337.  *                   widget.
  338.  *    Arguments: w - the toggle widget who's radio group we are getting.
  339.  *    Returns: the radio group associated with this toggle group.
  340.  */
  341.  
  342. static RadioGroup *
  343. GetRadioGroup(w)
  344. Widget w;
  345. {
  346.   ToggleWidget tw = (ToggleWidget) w;
  347.  
  348.   if (tw == NULL) return(NULL);
  349.   return( tw->toggle.radio_group );
  350. }
  351.  
  352. /*    Function Name: CreateRadioGroup
  353.  *    Description: Creates a radio group. give two widgets.
  354.  *    Arguments: w1, w2 - the toggle widgets to add to the radio group.
  355.  *    Returns: none.
  356.  * 
  357.  *      NOTE:  A pointer to the group is added to each widget's radio_group
  358.  *             field.
  359.  */
  360.  
  361. static void
  362. CreateRadioGroup(w1, w2)
  363. Widget w1, w2;
  364. {
  365.   char error_buf[BUFSIZ];
  366.   ToggleWidget tw1 = (ToggleWidget) w1;
  367.   ToggleWidget tw2 = (ToggleWidget) w2;
  368.  
  369.   if ( (tw1->toggle.radio_group != NULL) || (tw2->toggle.radio_group != NULL) ) {
  370.     sprintf(error_buf, "%s %s", "Toggle Widget Error - Attempting",
  371.         "to create a new toggle group, when one already exists.");
  372.     XtWarning(error_buf);
  373.   }
  374.  
  375.   AddToRadioGroup( NULL, w1 );
  376.   AddToRadioGroup( GetRadioGroup(w1), w2 );
  377. }
  378.  
  379. /*    Function Name: AddToRadioGroup
  380.  *    Description: Adds a toggle to the radio group.
  381.  *    Arguments: group - any element of the radio group the we are adding to.
  382.  *                 w - the new toggle widget to add to the group.
  383.  *    Returns: none.
  384.  */
  385.  
  386. static void
  387. AddToRadioGroup(group, w)
  388. RadioGroup * group;
  389. Widget w;
  390. {
  391.   ToggleWidget tw = (ToggleWidget) w;
  392.   RadioGroup * local;
  393.  
  394.   local = (RadioGroup *) XtMalloc( sizeof(RadioGroup) );
  395.   local->widget = w;
  396.   tw->toggle.radio_group = local;
  397.  
  398.   if (group == NULL) {        /* Creating new group. */
  399.     group = local;
  400.     group->next = NULL;
  401.     group->prev = NULL;
  402.     return;
  403.   }
  404.   local->prev = group;        /* Adding to previous group. */
  405.   if ((local->next = group->next) != NULL)
  406.       local->next->prev = local;
  407.   group->next = local;
  408. }
  409.  
  410. /*    Function Name: TurnOffRadioSiblings
  411.  *    Description: Deactivates all radio siblings.
  412.  *    Arguments: widget - a toggle widget.
  413.  *    Returns: none.
  414.  */
  415.  
  416. static void
  417. TurnOffRadioSiblings(w)
  418. Widget w;
  419. {
  420.   RadioGroup * group;
  421.   ToggleWidgetClass class = (ToggleWidgetClass) w->core.widget_class;
  422.  
  423.   if ( (group = GetRadioGroup(w)) == NULL)  /* Punt if there is no group */
  424.     return;
  425.  
  426.   /* Go to the top of the group. */
  427.  
  428.   for ( ; group->prev != NULL ; group = group->prev );
  429.  
  430.   while ( group != NULL ) {
  431.     ToggleWidget local_tog = (ToggleWidget) group->widget;
  432.     if ( local_tog->command.set ) {
  433.       class->toggle_class.Unset(group->widget, NULL, NULL, 0);
  434.       Notify( group->widget, NULL, NULL, 0);
  435.     }
  436.     group = group->next;
  437.   }
  438. }
  439.  
  440. /*    Function Name: RemoveFromRadioGroup
  441.  *    Description: Removes a toggle from a RadioGroup.
  442.  *    Arguments: w - the toggle widget to remove.
  443.  *    Returns: none.
  444.  */
  445.  
  446. static void
  447. RemoveFromRadioGroup(w)
  448. Widget w;
  449. {
  450.   RadioGroup * group = GetRadioGroup(w);
  451.   if (group != NULL) {
  452.     if (group->prev != NULL)
  453.       (group->prev)->next = group->next;
  454.     if (group->next != NULL)
  455.       (group->next)->prev = group->prev;
  456.     XtFree(group);
  457.   }
  458. }
  459.  
  460. /************************************************************
  461.  *
  462.  * Public Routines
  463.  *
  464.  ************************************************************/
  465.    
  466. /*    Function Name: XawToggleChangeRadioGroup
  467.  *    Description: Allows a toggle widget to change radio groups.
  468.  *    Arguments: w - The toggle widget to change groups.
  469.  *                 radio_group - any widget in the new group.
  470.  *    Returns: none.
  471.  */
  472.  
  473. void
  474. XawToggleChangeRadioGroup(w, radio_group)
  475. Widget w, radio_group;
  476. {
  477.   ToggleWidget tw = (ToggleWidget) w;
  478.  
  479.   RemoveFromRadioGroup(w);
  480.  
  481. /*
  482.  * If the toggle that we are about to add is set then we will 
  483.  * unset all toggles in the new radio group.
  484.  */
  485.  
  486.   if ( tw->command.set && radio_group != NULL )
  487.     XawToggleUnsetCurrent(radio_group);
  488.   AddToRadioGroup( GetRadioGroup(radio_group), w );
  489. }
  490.  
  491. /*    Function Name: XawToggleGetCurrent
  492.  *    Description: Returns the RadioData associated with the toggle
  493.  *                   widget that is currently active in a toggle group.
  494.  *    Arguments: w - any toggle widget in the toggle group.
  495.  *    Returns: The XtNradioData associated with the toggle widget.
  496.  */
  497.  
  498. caddr_t
  499. XawToggleGetCurrent(w)
  500. Widget w;
  501. {
  502.   RadioGroup * group;
  503.  
  504.   if ( (group = GetRadioGroup(w)) == NULL) return(NULL);
  505.   for ( ; group->prev != NULL ; group = group->prev);
  506.  
  507.   while ( group != NULL ) {
  508.     ToggleWidget local_tog = (ToggleWidget) group->widget;
  509.     if ( local_tog->command.set )
  510.       return( local_tog->toggle.radio_data );
  511.     group = group->next;
  512.   }
  513.   return(NULL);
  514. }
  515.  
  516. /*    Function Name: XawToggleSetCurrent
  517.  *    Description: Sets the Toggle widget associated with the
  518.  *                   radio_data specified.
  519.  *    Arguments: radio_group - any toggle widget in the toggle group.
  520.  *                 radio_data - radio data of the toggle widget to set.
  521.  *    Returns: none.
  522.  */
  523.  
  524. void
  525. XawToggleSetCurrent(radio_group, radio_data)
  526. Widget radio_group;
  527. caddr_t radio_data;
  528. {
  529.   RadioGroup * group;
  530.   ToggleWidget local_tog; 
  531.  
  532. /* Special case case of no radio group. */
  533.  
  534.   if ( (group = GetRadioGroup(radio_group)) == NULL) {
  535.     local_tog = (ToggleWidget) radio_group;
  536.     if ( (local_tog->toggle.radio_data == radio_data) )     
  537.       if (!local_tog->command.set) {
  538.     ToggleSet((Widget) local_tog, NULL, NULL, 0);
  539.     Notify((Widget) local_tog, NULL, NULL, 0);
  540.       }
  541.     return;
  542.   }
  543.  
  544. /*
  545.  * find top of radio_roup 
  546.  */
  547.  
  548.   for ( ; group->prev != NULL ; group = group->prev);
  549.  
  550. /*
  551.  * search for matching radio data.
  552.  */
  553.  
  554.   while ( group != NULL ) {
  555.     local_tog = (ToggleWidget) group->widget;
  556.     if ( (local_tog->toggle.radio_data == radio_data) ) {
  557.       if (!local_tog->command.set) { /* if not already set. */
  558.     ToggleSet((Widget) local_tog, NULL, NULL, 0);
  559.     Notify((Widget) local_tog, NULL, NULL, 0);
  560.       }
  561.       return;            /* found it, done */
  562.     }
  563.     group = group->next;
  564.   }
  565. }
  566.  
  567. /*    Function Name: XawToggleUnsetCurrent
  568.  *    Description: Unsets all Toggles in the radio_group specified.
  569.  *    Arguments: radio_group - any toggle widget in the toggle group.
  570.  *    Returns: none.
  571.  */
  572.  
  573. void
  574. XawToggleUnsetCurrent(radio_group)
  575. Widget radio_group;
  576. {
  577.   ToggleWidgetClass class;
  578.   ToggleWidget local_tog = (ToggleWidget) radio_group;
  579.  
  580.   /* Special Case no radio group. */
  581.  
  582.   if (local_tog->command.set) {
  583.     class = (ToggleWidgetClass) local_tog->core.widget_class;
  584.     class->toggle_class.Unset(radio_group, NULL, NULL, 0);
  585.     Notify(radio_group, NULL, NULL, 0);
  586.   }
  587.   if ( GetRadioGroup(radio_group) == NULL) return;
  588.   TurnOffRadioSiblings(radio_group);
  589. }
  590.